/* 
    数据库的客户端与服务器端也是TCP连接
    要经历三次握手和四次挥手
    为了防止连续的连接与断联，提高效率
    使用连接池，一次创建多次连接，每次取一个有效连接
    实现服务器和客户端的通信，大大减少了服务器和客户端连接的次数
    1.只需要一个连接池对象，应该使用单例
    2.设置最多连接和最少连接
    3.设置最长等待连接时间
    4.清除过多的空闲连接
    5.多线程访问同一个连接池，需要使用互斥锁
*/
#include <iostream>
#include <chrono>
#include "ConnectPool.h"

using namespace std;

void op1()
{
    const char *host = "localhost";
    const char *user = "root";
    const char *passwd = "1";

    for(int idx = 0; idx < 100; idx++)
    {
        /* 连接数据库 */
        MysqlConn conn;
        conn.connect("localhost", "root", "1", "musicDB");

        string sql = "insert into userInfo(username, age) value('zhangsan', 20);";

        /* 执行sql语句 */
        conn.update(sql);

    }

}

void op2(ConnectionPool * pool)
{
    for(int idx = 0; idx < 100; idx++)
    {
        shared_ptr<MysqlConn> conn = pool->getConnection();
        
        string sql = "insert into userInfo(username, age) value('zhangsan', 20);";
        
        conn->update(sql);
    }
}

void test()
{   

#if 0
//单线程不使用:55636
    chrono::_V2::steady_clock::time_point startTime = chrono::steady_clock::now();
    /* 不使用连接池 */
    op1();
    chrono::_V2::steady_clock::time_point endTime = chrono::steady_clock::now();

    auto interval = endTime - startTime;
    cout << "单线程不使用:" << interval.count() / 1000000 << endl;

#else
//单线程使用:24507
    chrono::_V2::steady_clock::time_point startTime = chrono::steady_clock::now();
    /* 使用连接池 */
    ConnectionPool * pool = ConnectionPool::getConnectPool();
    op2(pool);
    chrono::_V2::steady_clock::time_point endTime = chrono::steady_clock::now();
    auto interval = endTime - startTime;
    cout << "单线程使用:" << interval.count() / 1000000 << endl;
#endif
}

void test2()
{
#if 1
//多线程不使用:923
    MysqlConn conn;
    conn.connect("localhost", "root", "1", "musicDB");  // 防止多个线程同时使用相同的用户名和密码去连接数据库失败的情况
    chrono::_V2::steady_clock::time_point startTime = chrono::steady_clock::now();
    thread t1(op1);
    thread t2(op1);
    thread t3(op1);
    t1.join();
    t2.join();
    t3.join();
    chrono::_V2::steady_clock::time_point endTime = chrono::steady_clock::now();
    auto interval = endTime - startTime;
    cout << "多线程不使用:" << interval.count() / 1000000 << endl;

#else
//多线程使用:704
    chrono::_V2::steady_clock::time_point startTime = chrono::steady_clock::now();
    ConnectionPool * pool = ConnectionPool::getConnectPool();
    thread t1(op2, pool);
    thread t2(op2, pool);
    thread t3(op2, pool);
    t1.join();
    t2.join();
    t3.join();
    chrono::_V2::steady_clock::time_point endTime = chrono::steady_clock::now();
    auto interval = endTime - startTime;
    cout << "多线程使用:" << interval.count() / 1000000 << endl;

#endif

}

int main()
{
    test2();
    return 0;
}